package com.oig.sys.auth.service.impl;

import cn.hutool.core.util.StrUtil;
import com.lark.oapi.Client;
import com.lark.oapi.core.request.RequestOptions;
import com.lark.oapi.service.contact.v3.model.ChildrenDepartmentReq;
import com.lark.oapi.service.contact.v3.model.ChildrenDepartmentResp;
import com.lark.oapi.service.contact.v3.model.Department;
import com.lark.oapi.service.contact.v3.model.FindByDepartmentUserReq;
import com.lark.oapi.service.contact.v3.model.FindByDepartmentUserResp;
import com.lark.oapi.service.contact.v3.model.User;
import com.oig.sys.auth.constants.UserEnums;
import com.oig.sys.auth.dto.DepartmentDto;
import com.oig.sys.auth.dto.UserDto;
import com.oig.sys.auth.dto.UserMiniDto;
import com.oig.sys.auth.service.ITbDepartmentService;
import com.oig.sys.auth.service.ITbUserService;
import com.oig.sys.auth.service.IUserSyncService;
import com.oig.sys.auth.vo.DepartmentVo;
import com.oig.sys.auth.vo.UserVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserSyncServiceImpl implements IUserSyncService {

    private final ITbDepartmentService departmentService;
    private final ITbUserService userService;

    //@Async
    @Override
    public void syncDepartFromFeishu(String appId, String appSecret, Integer tenantId) throws Exception {
        Client client = Client.newBuilder(appId, appSecret).build();
        List<Integer> departmentIdList = new ArrayList<>();
        List<Integer> userIdList = new ArrayList<>();
        executeSyncDept(client, "0", tenantId, null, departmentIdList, userIdList);
        this.departmentService.delDepartmentNotInIdList(departmentIdList, tenantId);
        this.userService.cancelUserNotInListId(userIdList, tenantId);
    }

    private void executeSyncDept(Client client, String departmentId, Integer tenantId, DepartmentVo parentVo,
                                 List<Integer> departmentIdList,
                                 List<Integer> userIdList) throws Exception {
        ChildrenDepartmentReq req = ChildrenDepartmentReq.newBuilder()
                .userIdType("user_id")
                .departmentIdType("department_id")
                .departmentId(departmentId)
                .fetchChild(false)
                .pageSize(50)   //子部门列表一般不会超过50 就不分页了
                .build();
        ChildrenDepartmentResp resp = client.contact().department().children(req, RequestOptions.newBuilder().build());
        if (!resp.success()){
            log.error("查询飞书子部门失败：departmentId={}--{}", departmentId, resp.getMsg());
            return;
        }
        if (resp.getData()==null||resp.getData().getItems()==null){
            log.warn("没有部门数据：departmentId={}", departmentId);
            return ;
        }
        for (Department item : resp.getData().getItems()){
            DepartmentDto departmentDto = new DepartmentDto();
            departmentDto.setDepartCode(item.getDepartmentId());
            departmentDto.setDepartName(item.getName());
            if (parentVo!=null){
                departmentDto.setParentId(parentVo.getId());
                departmentDto.setParentName(parentVo.getDepartName());
            } else {
                departmentDto.setParentId(0);
                departmentDto.setParentName("无");
            }
            departmentDto.setTenantId(tenantId);
            List<UserVo> userVoList = this.executeSyncUsers(client, tenantId, item.getDepartmentId(), null, userIdList);
            log.debug("部门人数:{}",userVoList.size());
            List<UserMiniDto> userList = new ArrayList<>();
            for (UserVo userVo:userVoList){
                if (userVo.getCode().equals(item.getLeaderUserId())){
                    departmentDto.setMasterId(userVo.getId());
                    departmentDto.setMasterName(userVo.getRealName());
                }
                UserMiniDto userDto = new UserMiniDto();
                userDto.setId(userVo.getId());
                userDto.setName(userVo.getRealName());
                userList.add(userDto) ;
            }
            departmentDto.setUserList(userList);
            DepartmentVo departmentVo =this.departmentService.addOrUpdateDepartment(departmentDto);
            departmentIdList.add(departmentVo.getId());
            log.debug("add sub dept list:id={}",departmentVo.getId());
            this.executeSyncDept(client, item.getDepartmentId(), tenantId, departmentVo, departmentIdList, userIdList);
        }
    }

    private List<UserVo> executeSyncUsers(Client client, Integer tenantId, String departmentId, String pageToken,
                                          List<Integer> userIdList) throws Exception {
        log.debug("add sub or next page user list:departmentId={} ",departmentId);
        List<UserVo> userVoList = new ArrayList<>();
        FindByDepartmentUserReq req = FindByDepartmentUserReq.newBuilder()
                .userIdType("user_id")
                .departmentIdType("department_id")
                .departmentId(departmentId)
                .pageSize(50)   //最大50
                .pageToken(pageToken)
                .build();
        FindByDepartmentUserResp resp = client.contact().user().findByDepartment(req, RequestOptions.newBuilder().build());
        if (!resp.success()){
            log.error("查询飞书用户失败：departmentId={}---{}", departmentId, resp.getMsg());
            return userVoList;
        }
        if (resp.getData()==null||resp.getData().getItems()==null){
            log.warn("没有用户数据：departmentId={}", departmentId);
            return userVoList;
        }
        for (User item : resp.getData().getItems()) {
            if (StringUtils.isBlank(item.getEmployeeNo()) || !item.getStatus().getIsActivated()){
                log.warn("没有工号或者未激活用户：{}", item.getName());
                continue;
            }
            if (!item.getEmployeeNo().equals(item.getUserId())){
                log.warn("工号和飞书用户id不匹配：{}--{}", item.getEmployeeNo(), item.getUserId());
                continue;
            }
            UserDto userDto = new UserDto();
            userDto.setTenantId(tenantId);
            userDto.setFeishuUserId(item.getUserId());  //换成飞书userid
            userDto.setCode(item.getUserId());      //飞书id就是员工编号
            userDto.setPhone(item.getMobile()); //格式有 +86的     现在手机号没有做重复校验是可以重复使用的。
            if (StringUtils.isNotBlank(item.getNickname())){
                userDto.setNickName(item.getNickname());
            } else if (StringUtils.isNotBlank(item.getEnName())){
                userDto.setNickName(item.getEnName());
            } else {
                userDto.setNickName(item.getName());
            }
            //账户换成Y加工号
            userDto.setUsername("Y"+item.getEmployeeNo());
            userDto.setRealName(item.getName());
            userDto.setEmail(item.getEmail());
            if (item.getGender()!=null){
                userDto.setSex(UserEnums.SexEnum.getCodeByGender(item.getGender()));
            }
            UserVo userVo = userService.addOrUpdateUser(userDto);   //不加try catch，有保存说明需要改程序
            if (userIdList!=null) userIdList.add(userVo.getId());
            userVoList.add(userVo);
        }
        if (StrUtil.isNotBlank(resp.getData().getPageToken())) {
            userVoList.addAll(executeSyncUsers(client, tenantId, departmentId, resp.getData().getPageToken(), userIdList));
        }
        return userVoList;
    }


    @Override
    public void syncUserFromFeishu(String appId, String appSecret, Integer tenantId) throws Exception {
        Client client = Client.newBuilder(appId, appSecret).build();
        List<UserVo> userVoList = new ArrayList<>();
        executeSyncUserByDeptId(client, "0", tenantId,  userVoList);
        List<Integer> userIdList = userVoList.stream().map(UserVo::getId).collect(Collectors.toList());
        this.userService.cancelUserNotInListId(userIdList, tenantId);
    }



    private void executeSyncUserByDeptId(Client client, String departmentId, Integer tenantId, List<UserVo> userVoList) throws Exception {
        ChildrenDepartmentReq req = ChildrenDepartmentReq.newBuilder()
                .userIdType("user_id")
                .departmentIdType("department_id")
                .departmentId(departmentId)
                .fetchChild(false)
                .pageSize(50)   //子部门列表一般不会超过50 就不分页了
                .build();
        ChildrenDepartmentResp resp = client.contact().department().children(req, RequestOptions.newBuilder().build());
        if (!resp.success()){
            log.error("sync user 查询飞书子部门失败：departmentId={}--{}", departmentId, resp.getMsg());
            return;
        }
        if (resp.getData()==null||resp.getData().getItems()==null){
            log.warn("没有部门数据：departmentId={}", departmentId);
            return ;
        }
        for (Department item : resp.getData().getItems()){
            userVoList.addAll(this.executeSyncUsers(client, tenantId, item.getDepartmentId(), null, null));
            executeSyncUserByDeptId(client, item.getDepartmentId(), tenantId, userVoList);
        }
    }





}
